/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	gpio.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-06-17
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "mbuf.h"



/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/





/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/




 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
static OS_MEM   buf_mem;

static struct mbuf buf_pool[CFG_MBUF_POOL_SIZE] = {0};

/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/



/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/

int mbuf_init(void)
{
    OS_ERR err;

    /* 初始化小块内存池 */
    OSMemCreate(&buf_mem,
                 "mbuf_pool",
                 (void*)&buf_pool[0],
                 CFG_MBUF_POOL_SIZE,
                 sizeof(struct mbuf),
                 &err);

    if( err != OS_ERR_NONE )
    {
        Error_Log("sbscp buf pool create failed!\n");
        return -1;
    }

    return 0;
}

/*
 *******************************************************************************
 *  @brief   mbuf_alloc 分配一块固定大小的内存
 *  @param   size 表示数据域的大小，实际分配内存为，20字节头部+size,大小的内存
 *  @return  返回分配的内存链，如果分配失败返回NULL
 *******************************************************************************
 */
struct mbuf *mbuf_alloc(uint16_t size)
{
	struct mbuf *r,*q;
	struct mbuf* p_head = NULL;
	OS_ERR err;
	
	do{
		q = (struct mbuf *)OSMemGet(&buf_mem, &err);
			
		if( err != OS_ERR_NONE )
		{
			Trace_Log("mbuf malloc failed!\n");
			/* 释放已分配内存 */
			if(p_head != NULL)
			{
				mbuf_free(p_head);
				p_head = NULL;
			}
			return NULL;
		}
		/* 初始化内存块 */
		q->next    = NULL;
		q->tot_len = size;
		memset(q->payload, 0, MBUF_SIZE);
		
		/* 串联内存块 */
		if(p_head != NULL)
		{
			r->next = q;
			r = q;
		}else{
			p_head = q;
			r = p_head;
		}
		if(size > MBUF_SIZE)
		{
			size -= MBUF_SIZE;	
		}else{
			size = 0;
		}	
	}while(size);
	
	return p_head;
}

/*
 *******************************************************************************
 *  @brief   mbuf_free 释放内存
 *  @param   size 表示数据域的大小，实际分配内存为，20字节头部+size,大小的内存
 *  @return  返回分配的内存链，如果分配失败返回NULL
 *******************************************************************************
 */
uint8_t mbuf_free(struct mbuf *p)
{
    OS_ERR err;
	
	
	if( p == NULL )
	{
		return 0;
	}
	
	struct mbuf *q = p;
	
	while( p != NULL )
	{
		q = p->next;
		
		OSMemPut(&buf_mem,p,&err);

//		Debug_Log("Free a buf addr is %p\n",p);

		p = q;
	}

	return 0;
}

/*
 *******************************************************************************
 *  @brief   mbuf_read 将buf里的内容从头部开始完全读出到指定的内存中去
 *  @param   p 需要读取的buf块
 *           p_read 读取后存放的内存指针
 *           size   需要读取的最大值
 *  @return  -1  读取失败
 *           大于等于0 表示读取的字节数
 *******************************************************************************
 */
int mbuf_read(struct mbuf *p,uint8_t *p_read,uint16_t size)
{
    uint16_t index = 0;
    uint16_t temp  = 0;

    while( p != NULL && size != 0 )
    {
        temp = p->tot_len;
        
        if( temp > MBUF_SIZE  )
        {
            temp = MBUF_SIZE;
        }

        memcpy(p_read+index, p->payload, temp);
        
        size  -= temp;
        index += temp;
        p = p->next;
    }

    return index;
}

/*
 *******************************************************************************
 *  @brief   mbuf_write_total 内存指向的内容写入buf控制块，从头部开始写入
 *  @param   p 需要写入的buf块
 *           p_write 需要写入存放的内存指针
 *           size    写入内存的大小
 *  @return  -1  写入失败
 *           大于等于0 表示写入的字节数
 *******************************************************************************
 */
int mbuf_write(struct mbuf *p, uint8_t *p_write, uint16_t size)
{
    if( p == NULL )
    {
        return -1;
    }

    if( size > p->tot_len ) 
    {
        return 0;
    }

    uint16_t index = 0;
    uint16_t temp  = 0;

    while( p != NULL && size != 0 )
    {
        temp  = MBUF_SIZE;

        if( size <= temp )
        {
            temp = size;
        }
        
        memcpy(p->payload, p_write+index, temp);
        
        size  -= temp;
        index += temp;    
        p = p->next;
    }

    return index;
}
